<template>
  <div class="table-box">
    <pro-table ref="proTableRef" row-key="id" :columns="columns" :pagination="false" :request-api="getMenuTreeApi">
      <!-- 表格 header 按钮 -->
      <template #tableHeader>
        <el-button v-auth="'sys:menu:add'" type="primary" :icon="CirclePlus" @click="handleAdd()">新增菜单 </el-button>
      </template>
      <!-- 菜单名称 -->
      <template #title="{ row }">
        {{ row.title }}
        <template v-if="row.isHide">
          <span style="margin-left: 5px; color: #f56c6c"> ( 隐藏 ) </span>
        </template>
      </template>
      <!-- 菜单图标 -->
      <template #icon="{ row }">
        <el-icon v-if="row.icon" :size="18">
          <component :is="row.icon"></component>
        </el-icon>
      </template>
      <!-- 组件路径 -->
      <template #component="{ row }">
        {{ row.component || row.link }}
      </template>
      <!-- 状态 -->
      <template #isEnable="scope">
        <el-switch
          v-model="scope.row.isEnable"
          :loading="scope.row.loading"
          active-text="已启用"
          inactive-text="已禁用"
          inline-prompt
          :before-change="handleEnable.bind(scope, scope.row)"
        />
      </template>
      <!-- 菜单操作 -->
      <template #operation="{ row }">
        <el-button v-auth="'sys:menu:add'" type="primary" link :icon="Plus" @click="handleAdd(row)"> 下级 </el-button>
        <el-button v-auth="'sys:menu:edit'" type="primary" link :icon="EditPen" @click="handleEdit(row)"> 编辑 </el-button>
        <el-button v-auth="'sys:menu:del'" type="danger" link :icon="Delete" @click="handleDelete(row)"> 删除 </el-button>
      </template>
    </pro-table>
    <!-- 编辑菜单 -->
    <menu-edit ref="editDialogRef" />
  </div>
</template>

<script setup lang="ts">
import type { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
import type { SysMenu } from "@/api/interface";
import { ref } from "vue";
import { useHandleData } from "@/hooks/useHandleData";
import { statusConst, menuTypeConst } from "@/utils/dict";
import { Delete, EditPen, Plus, CirclePlus } from "@element-plus/icons-vue";
import { addMenuApi, editMenuApi, switchEnableMenuApi, deleteMenuApi, getMenuTreeApi } from "@/api/modules/system/menu";
import ProTable from "@/components/ProTable/index.vue";
import MenuEdit from "./components/edit.vue";

defineOptions({
  name: "SystemMenu"
});

/** 表格实例 */
const proTableRef = ref<ProTableInstance>();
/** 编辑弹窗实例 */
const editDialogRef = ref<InstanceType<typeof MenuEdit> | null>(null);

/** 表格配置项 */
const columns: ColumnProps[] = [
  { prop: "title", label: "菜单名称", align: "left", search: { el: "input" } },
  { prop: "icon", label: "图标", width: 100 },
  { prop: "name", label: "Name" },
  { prop: "component", label: "组件路径", width: 400 },
  { prop: "sort", label: "权重(排序)", width: 100 },
  { prop: "menuType", label: "类型", width: 100, tag: true, enum: menuTypeConst },
  { prop: "isEnable", label: "状态", width: 100, enum: statusConst, search: { el: "select" } },
  { prop: "operation", label: "操作", width: 220, fixed: "right" }
];

/**
 * 添加菜单
 *
 * @param param 选中的菜单
 * @returns void
 */
const handleAdd = (param?: Partial<SysMenu.Result>) => {
  const editParams = {
    title: "添加菜单",
    menu: {
      pid: param?.id,
      menuType: 0,
      sort: 0,
      splicingMethod: 0
    },
    getTableList: proTableRef.value?.getTableList,
    submitApi: addMenuApi
  };
  editDialogRef.value?.acceptParams(editParams);
};

/**
 * 编辑菜单
 *
 * @param param 选中的菜单
 * @returns void
 */
const handleEdit = (param: Partial<SysMenu.Result>) => {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const { children: _, ...menu } = param;
  const editParams = {
    title: "编辑菜单",
    menu,
    getTableList: proTableRef.value?.getTableList,
    submitApi: editMenuApi
  };
  editDialogRef.value?.acceptParams(editParams);
};

/**
 * 启用/禁用菜单
 *
 * @param param 选中的菜单
 * @returns 设置结果
 */
const handleEnable = (param: Partial<SysMenu.Result> & { loading?: boolean }) => {
  param.loading = true;
  return switchEnableMenuApi({ id: param.id! })
    .then(({ data }) => {
      if (data) {
        return Promise.resolve(true);
      } else return Promise.reject(new Error("修改状态失败"));
    })
    .finally(() => {
      param.loading = false;
    });
};

/**
 * 删除菜单
 *
 * @param param 选中的菜单
 * @returns void
 */
const handleDelete = (param: Partial<SysMenu.Result>) => {
  useHandleData(deleteMenuApi, { ids: [param.id] }, `删除【${param.title}】菜单`).then(res => {
    if (res) proTableRef.value?.getTableList();
  });
};
</script>

<style lang="scss" scoped>
.menu-title {
  display: inline-flex;
  align-items: center;
  .el-icon {
    margin-right: 5px;
  }
}
</style>
